import 'package:my_flutter_core/services/data_sharing.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// A service to get/set data on local device.
/// Local device data access is slow. So we cached each data to boost performance.
class LocalStorage {
  static SharedPreferences? _prefs;

  /// Checks if the local storage contains data with [key].
  static Future<bool> containsKey(String key) async {
    final prefs = await (_getPreferences());
    return prefs.containsKey(key);
  }

  /// Removes the data from local storage and cache by [key].
  static Future<void> remove(String key) async {
    final prefs = await (_getPreferences());
    prefs.remove(key);
    DataSharing.remove(key: key);
  }

  /// Clears local storage and cache.
  static Future<void> clear() async {
    final prefs = await (_getPreferences());
    prefs.clear();
    DataSharing.clear();
  }

  /// Gets the data by the [key]. If it is not cached yet then the data will be get from the local storage.
  /// By now the T supports [String], [bool], [double] and [int] type.
  static Future<T?> get<T>(String key) async {
    var value = DataSharing.get<T>(key);

    if (value == null) {
      final prefs = await _getPreferences();
      final dynamic storedValue;

      if (T == String) {
        storedValue = prefs.getString(key);
      } else if (T == bool) {
        storedValue = prefs.getBool(key);
      } else if (T == double) {
        storedValue = prefs.getDouble(key);
      } else if (T == int) {
        storedValue = prefs.getInt(key);
      } else {
        storedValue = prefs.get(key);
      }

      DataSharing.set<T>(key, storedValue as T?);
      value = storedValue;
    }

    return value;
  }

  /// Sets the data by the [key] and [value]. The cache is updated, too.
  /// By now the T supports [String], [bool], [double] and [int] type.
  static Future<void> set<T>(String key, T? value) async {
    final prefs = await _getPreferences();

    if (T == String) {
      prefs.setString(key, value as String);
    } else if (T == bool) {
      prefs.setBool(key, value as bool);
    } else if (T == double) {
      prefs.setDouble(key, value as double);
    } else if (T == int) {
      prefs.setInt(key, value as int);
    }

    DataSharing.set<T>(key, value);
  }

  /// Gets the library class instance to interact with local storage.
  static Future<SharedPreferences> _getPreferences() async =>
      _prefs ??= await SharedPreferences.getInstance();
}
